import { Chart } from '@antv/g2';
import React from 'react';
import ResizePolyfill from 'resize-observer-polyfill';
import { debounce } from 'lodash';

let uniqueId = 0;
function generateUniqueId() {
  return `rc-g2-${uniqueId++}`;
}
interface IProps {
  data?: any;
  width?: number;
  height?: number;
  chartConfig?: {};
  configs?: any;
}

export default function createG2(__operation: any) {
  class Component extends React.Component<IProps> {
    private chart: any;
    private chartId: any;

    constructor(props: any, context: any) {
      super(props, context);
      this.chart = null;
      // @ts-ignore
      this.onRef = null;
      // @ts-ignore
      this.resizeObserverObj = this.resizeObserver();
      this.chartId = generateUniqueId();
    }

    componentDidMount() {
      this.initChart(this.props);

      //dom对象发生变化后的操作逻辑赋值给dom对象
      // @ts-ignore
      this.onRef.handleResize = this.handleResize;
      //观察的对象
      // @ts-ignore
      this.resizeObserverObj.observe(this.onRef);
    }

    componentWillReceiveProps(newProps: any) {
      const { data: newData, width: newWidth, height: newHeight } = newProps;
      const { data: oldData, width: oldWidth, height: oldHeight } = this.props;

      if (newData !== oldData) {
        this.chart.changeData(newData);
      }
      if (newWidth !== oldWidth || newHeight !== oldHeight) {
        this.chart.changeSize(newWidth, newHeight);
      }
    }

    shouldComponentUpdate() {
      return false;
    }

    componentWillUnmount() {
      this.chart.destroy();
      this.chart = null;
      this.chartId = null;
      // @ts-ignore
      this.resizeObserverObj.unobserve(this.onRef);
    }

    // 实例化监听DOM变化对象
    resizeObserver() {
      // @ts-ignore
      if (window.resizeObserver) {
        // @ts-ignore
        return window.resizeObserver;
      }
      // @ts-ignore
      let observer = window.resizeObserver;
      if (!observer) {
        observer = ResizePolyfill;
      }

      return new observer((entities: any) => {
        if (entities && entities.length) {
          entities.forEach((entity: any) => {
            //contentRect:位置大小信息
            //target:dom信息
            const { contentRect, target } = entity;
            const { handleResize } = target;
            if (handleResize) {
              handleResize(contentRect, target); //目标对象发生改变之后的逻辑操作
            }
          });
        }
      });
    }

    // 容器宽高变化重新更改图表宽高
    // @ts-ignore
    handleResize = debounce((contentRect, ele) => {
      if (this.chart) {
        this.chart.changeSize(ele.offsetWidth, ele.offsetHeight);
      }
    }, 400);

    initChart(props: IProps) {
      const { width, height, data, chartConfig, configs } = props;
      const chart = new Chart({
        container: this.chartId,
        width,
        height,
        autoFit: true,
        appendPadding: [10, 0, 0, 0],
        ...chartConfig,
      });
      chart.data(data);
      __operation(chart, configs);
      this.chart = chart;
    }

    render() {
      // @ts-ignore
      return (
        <div
          id={this.chartId}
          // @ts-ignore
          ref={(ref) => (this.onRef = ref)}
          style={{ width: '100%', height: '100%' }}
        />
      );
    }
  }

  return Component;
}
